﻿using System.Linq;
using System.Net;
using System.Xml.Linq;
using SharePhone.Common;

namespace SharePhone.Provider.WebServices
{
    public delegate void GetSearchMetadataCompleteHandler(object sender, RequestCompleteEventArgs e);

    public delegate void QueryCompleteHandler(object sender, RequestCompleteEventArgs e);

    public class SPSearchService : BaseWebService
    {
        private const string URL = "/_vti_bin/Search.asmx";
        private const string ActionQuery = "urn:Microsoft.Search/Query";

        private const string ActionGetSearchMetaData =
            "http://microsoft.com/webservices/OfficeServer/QueryService/GetSearchMetadata";

        private const string SoapQuery = @"<Query xmlns='urn:Microsoft.Search'><queryXml>{0}</queryXml></Query>";

        private const string SoapGetSearchMetadata =
            @"<GetSearchMetadata xmlns='http://microsoft.com/webservices/OfficeServer/QueryService' />";

        private readonly CredentialSettings credentials;

        public SPSearchService(string baseUrl, CredentialSettings credentials)
        {
            BaseUrl = baseUrl;
            this.credentials = credentials;
        }

        public event GetSearchMetadataCompleteHandler GetSearchMetadataCompleted;
        public event QueryCompleteHandler QueryCompleted;

        public void QueryAsync(string queryXml)
        {
            queryXml = HttpUtility.HtmlEncode(queryXml);
            GetResponse(ActionQuery, string.Format(SoapQuery, queryXml), GetNetworkCredential(credentials),
                        (object sender, RequestCompleteEventArgs e) =>
                            {
                                XElement result =
                                    e.Result.Descendants(XName.Get("QueryResult", "urn:Microsoft.Search")).
                                        FirstOrDefault();
                                OnQueryCompleted(result);
                            });
        }

        public void GetSearchMetadataAsync()
        {
            GetResponse(ActionGetSearchMetaData, SoapGetSearchMetadata, GetNetworkCredential(credentials),
                        (object sender, RequestCompleteEventArgs e) =>
                            {
                                XElement result = e.Result.Descendants(XName.Get("SearchMetadata", "")).FirstOrDefault();
                                OnGetSearchMetadataCompleted(result);
                            });
        }

        internal override string GetUrl()
        {
            return BaseUrl + URL;
        }

        protected void OnGetSearchMetadataCompleted(XElement result)
        {
            if (GetSearchMetadataCompleted != null)
                GetSearchMetadataCompleted(this, new RequestCompleteEventArgs(result));
        }

        protected void OnQueryCompleted(XElement result)
        {
            if (QueryCompleted != null)
                QueryCompleted(this, new RequestCompleteEventArgs(result));
        }
    }
}